{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 获取对象信息\n",
    "\n",
    "当我们拿到一个对象的引用时，如何知道这个对象是什么类型、有哪些方法呢？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## type()\n",
    "\n",
    "使用<font color=red>type()</font>函数来判断对象类型；基本类型都可以用<font color=red>type()</font>来判断.\n",
    "\n",
    "由下式可知, 函数 <font color=red>type()</font>的返回类型为<font color=red>class</font>."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'int'>\n",
      "<class 'str'>\n",
      "<class 'NoneType'>\n",
      "<class 'builtin_function_or_method'>\n",
      "<class '__main__.Ananimal'>\n"
     ]
    }
   ],
   "source": [
    "print(type(123))\n",
    "print(type('str'))\n",
    "print(type(None))\n",
    "\n",
    "class Ananimal(object):\n",
    "    pass\n",
    "\n",
    "a = Ananimal()\n",
    "print(type(abs)) # type指向的是一个函数\n",
    "print(type(a)) # type指向的是一个类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n",
      "True\n",
      "False\n",
      "True\n",
      "False\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# 比较两个变量的类型是否相同\n",
    "print(type(123) == type(456))\n",
    "print(type(123) == int)\n",
    "print(type('abc') == type('123'))\n",
    "print(type('abc') == str)\n",
    "print(type('abc') == type(123))\n",
    "\n",
    "# 判断一个对象是否为函数,可以使用 types 模块\n",
    "import types\n",
    "\n",
    "def fn():\n",
    "    pass\n",
    "\n",
    "print(type(fn) == types.FunctionType)\n",
    "print(type(abs) == types.FunctionType)\n",
    "print(type(lambda x: x) == types.LambdaType)\n",
    "print(type(x for x in range(10)) == types.GeneratorType)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## isinstance()\n",
    "\n",
    "1. 可以判断一个对象（变量）是否是某一个类的实例；\n",
    "2. 可以判断一个变量是否是某些类型中的一种；\n",
    "3. 总是优先使用<font color=red>isinstance()</font>来判断类型；"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "a <class 'str'>\n",
      "123 <class 'int'>\n",
      "b'a' <class 'bytes'>\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "class Animal():\n",
    "    pass\n",
    "\n",
    "a = Animal()\n",
    "print(isinstance(a , Animal))\n",
    "print('a', str)\n",
    "print(123, int)\n",
    "print(b'a', bytes)\n",
    "print(isinstance([1, 2, 3], (list, tuple)))\n",
    "#print(isinstance((1, 2, 3)，(list, tuple)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## dir()\n",
    "\n",
    "1. <font color=red>dir()</font>函数可以获取一个对象的所有属性和方法\n",
    "2. 它返回一个包含字符串的list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']\n",
      "3\n",
      "3\n",
      "True\n",
      "False\n",
      "None\n",
      "True\n",
      "19\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'MyObject' object has no attribute 'z'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-12-eac941a506f3>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m     16\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhasattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'y'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     17\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'y'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# 获取对象属性'y'\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 18\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'z'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# 如果试图获取不存在的属性, 会抛出AttributeError的错误\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     19\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mgetattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'z'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m404\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# 获取属性'z'，如果不存在，返回默认值404\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     20\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhasattr\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'power'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# 检测是否有函数属性\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAttributeError\u001b[0m: 'MyObject' object has no attribute 'z'"
     ]
    }
   ],
   "source": [
    "print(dir('ABC'))\n",
    "print(len('ABC'))\n",
    "print('ABC'.__len__()) # 获取长度信息\n",
    "\n",
    "class MyObject(object):\n",
    "    def __init__(self):\n",
    "        self.x = 9\n",
    "        \n",
    "    def power(self):\n",
    "        return self.x * self.x\n",
    "    \n",
    "obj = MyObject()\n",
    "print(hasattr(obj, 'x')) # 测试对象obj是否有'x'\n",
    "print(hasattr(obj, 'y'))\n",
    "print(setattr(obj, 'y', 19)) # 给对象设置属性'y'\n",
    "print(hasattr(obj, 'y'))\n",
    "print(getattr(obj, 'y')) # 获取对象属性'y'\n",
    "print(getattr(obj, 'z')) # 如果试图获取不存在的属性, 会抛出AttributeError的错误\n",
    "print(getattr(obj, 'z', 404)) # 获取属性'z'，如果不存在，返回默认值404\n",
    "print(hasattr(obj, 'power')) # 检测是否有函数属性\n",
    "fn = getattr(obj, 'power') # 获取属性'power'并赋给变量fn\n",
    "print(fn())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
